package badugaserver;

/**
 * @author Wojtek N., Kamil M.
 * @version 0.7
 * The main class of the ranking select class.
 */
 
 public class Ranking
 {
	/**
	 * Method which removes from player hand invalid cards.
	 * @param hand given hand to check
	 * @return refactored hand
	 */
	private static Hand checkForSimilarities(Hand hand)
	{
		Hand temp = hand;
		for(int i=0; i<4; i++)
		{
			int size = temp.size();
			// if card have same suit with some other card then
			if(temp.getCard(i%size).getSuit() == temp.getCard((i+1)%size).getSuit() || temp.getCard(i%size).getSuit() == temp.getCard((i+2)%size).getSuit() || temp.getCard(i%size).getSuit() == temp.getCard((i+3)%size).getSuit())
			{
				// if card have same rank with some other card then
				if(temp.getCard(i%size).getRank() == temp.getCard((i+1)%size).getRank() || temp.getCard(i%size).getRank() == temp.getCard((i+2)%size).getRank() || temp.getCard(i%size).getRank() == temp.getCard((i+3)%size).getRank())
				{
					// check if card is highest rank; if is remove it, else leave it be
					if(temp.getCard(i%size).getRank() > temp.getCard((i+1)%size).getRank() || temp.getCard(i%size).getRank() > temp.getCard((i+2)%size).getRank() || temp.getCard(i%size).getRank() > temp.getCard((i+3)%size).getRank())
					{
						temp.removeCard(i);
					}
				}
				// if card have only same suit with some other card then
				else
				{
					// check if card is highest rank; if is remove it, else leave it be
					if(temp.getCard(i%size).getRank() > temp.getCard((i+1)%size).getRank() || temp.getCard(i%size).getRank() > temp.getCard((i+2)%size).getRank() || temp.getCard(i%size).getRank() > temp.getCard((i+3)%size).getRank())
					{
						temp.removeCard(i);
					}
				}
			}
			// if card have same rank with some other card then
			else if(temp.getCard(i%size).getRank() == temp.getCard((i+1)%size).getRank() || temp.getCard(i%size).getRank() == temp.getCard((i+2)%size).getRank() || temp.getCard(i%size).getRank() == temp.getCard((i+3)%size).getRank())
			{
				// check if card is highest rank; if is remove it, else leave it be
				if(temp.getCard(i%size).getRank() > temp.getCard((i+1)%size).getRank() || temp.getCard(i%size).getRank() > temp.getCard((i+2)%size).getRank() || temp.getCard(i%size).getRank() > temp.getCard((i+3)%size).getRank())
				{
					temp.removeCard(i);
				}
			}
		}
		return temp;
	}
 
	/** 
	 * Counts rank of the full hand.
	 * @param hand given hand to count its value
	 * @return value of the hand
	 */
	private static int rankCards(Hand hand)
	{
		int size = hand.size();
		int sumUp = 0;
		
		for(int i=0; i<size; i++)
		{
			sumUp = sumUp + hand.getCard(i).getRank();
		}
		return sumUp;
	}
 
	/**
	 * Method to compare 2 hands.
	 * @return 0 if given hand are the same; 1 if left hand have greater rank or have more cards after selection than right hand; -1 if right hand have greater rank or have more cards after selection than left hand
	 */
	private static int compareHands(Hand hand_1, Hand hand_2)
	{	
		hand_1 = checkForSimilarities(hand_1);
		hand_2 = checkForSimilarities(hand_2);
		int rank_1 = rankCards(hand_1);
		int rank_2 = rankCards(hand_2);
		if(hand_1.size() == hand_2.size())
		{
			if(rank_1 < rank_2)
			{
				return 1;
			}
			else if (rank_1 == rank_2)
			{
				return 0;
			}
			else
			{
				return -1;
			}
		}
		else if(hand_1.size()<hand_2.size())
		{
			return -1;
		}
		else
		{
			return 1;
		}
		
	}
	
	/**
	 * Simple power function for integers.
	 * @param a the base
	 * @param b the exponent
	 * @return the value a^b
	 */
	private static int pow(int a, int b)
	{
		int result = a;
		if(b>0)
		{
			for(int i=1; i<=b; i++)
			{
				result = result*a;
			}
			return result;
		}
		else
		{
			return 1;
		}
	}
 
	/**
	 * Method which selects winner (or winners if draw) from given hands.
	 * @param hands table of all hands which are left in the game
	 * @return the winner as a single digit or if there was a draw - multiple digit (for example hand[1] and hand[4] won, than returned value is 14)
	 */
	public static int lookForTheWinner(Hand[] hands)
	{
		int allPlayers = hands.length;
		int winner = -1;
		int[] drawers = new int[allPlayers];
		for(int i=0; i<allPlayers; i++)
		{
			drawers[i] = 0;
		}
		int howManyDrawers = 0;
		
		
		for(int i=0; i<allPlayers; i++)
		{
			int temp = i+1;
			while(temp != allPlayers)
			{
				if(compareHands(hands[i], hands[temp]) == 0)
				{
					if(drawers[i] == 0)
					{
						drawers[i] = 1;
						drawers[temp] = 1;
					}
				}
				else if(compareHands(hands[i], hands[temp]) == 1)
				{
					winner = temp;
				}
				else if(compareHands(hands[i], hands[temp]) == -1)
				{
					winner = i;
				}
				temp++;
			}
		}
		
		for(int i=0; i<allPlayers; i++)
		{
			if(drawers[i] != 0)
			{
				howManyDrawers++;
			}
		}
		if(howManyDrawers != 0)
		{
			for(int i=0; i<allPlayers; i++)
			{
				if(drawers[i] != 0)
				{
					winner = drawers[i]*pow(10, howManyDrawers);
					howManyDrawers--;
				}
			}
		}
		return winner;
	}
 
 }
 
 